﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.DataModel;
using YArchitech.HVAC;
using YArchitech.LIB;
using YArchitech.MEP;
using YArchitech.Revit;

namespace YArchitech.Plumbing
{
	public class LaySprinklerHelper
	{
		public LaySprinklerHelper(UIApplication uiApp, UIDocument uiDoc, ref string message, SprinklersParam sprinklersPara, int sprinklerCategory, int sprinlkerLocationType)
		{
			this.message = message;
			this.uiApp = uiApp;
			this.doc = uiDoc.Document;
			this.sel = uiDoc.Selection;
			this.sprinklersPara = sprinklersPara;
			this.sprinklerCategory = sprinklerCategory;
			this.sprinlkerLocationType = sprinlkerLocationType;
		}

		public LaySprinklerHelper(Autodesk.Revit.DB.Document doc)
		{
			this.doc = doc;
		}

		public bool LayPointSprinkler(FamilySymbol fs, int current)
		{
			ISelectionFilter selectionFilter = new LaySprinklerHelper.SprinlkersPipeSelectionFilter();
			SpaceFamilyDataReader spaceFamilyDataReader = new SpaceFamilyDataReader();
			SprinklerShelter sprinklerShelter = new SprinklerShelter();
			try
			{
				FamilySymbol familySymbol;
				if (current == 0)
				{
					familySymbol = spaceFamilyDataReader.GetFamilySymbolByIdSubTran(this.sprinklersPara.Id, "Sprinkler", this.sprinklersPara.SymbolName, this.doc, BuiltInCategory.OST_Sprinklers);
				}
				else
				{
					familySymbol = fs;
				}
				Reference reference = this.sel.PickObject((Autodesk.Revit.UI.Selection.ObjectType)1, selectionFilter, "请选择一根喷淋系统管道");
				Pipe pipe = this.doc.GetElement(reference) as Pipe;
				PipeType pipeType = pipe.PipeType;
				YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(pipe);
				if (this.sprinklerCategory == 1 || this.sprinklerCategory == 3)
				{
					if (this.sprinklersPara.OffSet * 1000.0 / 304.8 + this.GetLevelZValue() <= hypiping.StartConnector.Origin.Z)
					{
						int num = this.sprinklerCategory;
						if (num != 1)
						{
							if (num == 3)
							{
								YJKMessageBox.Information("侧喷喷头应位于管道上方。");
							}
						}
						else
						{
							YJKMessageBox.Information("上喷喷头应位于管道上方。");
						}
						return false;
					}
					if (this.sprinklerCategory == 3)
					{
						this.sprinklerCategory = 1;
					}
				}
				if (this.sprinklerCategory == 2 || this.sprinklerCategory == 4)
				{
					if (this.sprinklersPara.OffSet * 1000.0 / 304.8 + this.GetLevelZValue() >= hypiping.StartConnector.Origin.Z)
					{
						int num = this.sprinklerCategory;
						if (num != 2)
						{
							if (num == 4)
							{
								YJKMessageBox.Information("水幕喷头应位于管道下方。");
							}
						}
						else
						{
							YJKMessageBox.Information("下喷喷头应位于管道下方。");
						}
						return false;
					}
					if (this.sprinklerCategory == 4)
					{
						this.sprinklerCategory = 2;
					}
				}
				UnifiedModified.ActivateFamilySymbol(familySymbol);
				ICollection<ElementId> priorFitting = sprinklerShelter.GetPriorFitting(this.doc);
				XYZ layPoint = this.GetLayPoint(reference);
				if (layPoint == null)
				{
					return true;
				}
				Element element = this.LaySprinkerAndRotate(pipe, layPoint, familySymbol);
				Pipe pipe2 = this.SetSprinklerParam(element);
				if (pipe2 == null)
				{
					this.ConnPointSprinkler(element, pipe);
				}
				else
				{
					this.ConnUpDownSprinkler(pipe, pipe2, layPoint);
				}
				sprinklerShelter.SetAfterFitting(this.doc, priorFitting, familySymbol, pipeType, false, null);
			}
			catch (Exception ex)
			{
				this.message = ex.Message;
				return false;
			}
			return true;
		}

		private double GetLevelZValue()
		{
			return this.doc.ActiveView.GenLevel.Elevation;
		}

		private XYZ GetLayPoint(Reference refPipe)
		{
			YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(this.doc.GetElement(refPipe) as Pipe);
			XYZ xyz;
			if (this.sprinlkerLocationType == 1)
			{
				xyz = refPipe.GlobalPoint;
			}
			else
			{
				xyz = this.sel.PickPoint("请选择喷头偏移方向");
				if (hypiping.GetXYVectorPointToPiping(xyz).GetLength() == 0.0)
				{
					YJKMessageBox.Information("偏移方向不可和管道一致！");
					return null;
				}
				xyz = hypiping.GetLineProject(xyz) - hypiping.GetXYVectorPointToPiping(xyz) * (this.sprinklersPara.SprinlkerDistance / 304.8);
			}
			return xyz;
		}

		private Element LaySprinkerAndRotate(Pipe pipe, XYZ xyzPoint, FamilySymbol familySymbol)
		{
			xyzPoint = new XYZ(xyzPoint.X, xyzPoint.Y, 0.0);
			YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(pipe);
			XYZ origin = hypiping.StartConnector.Origin;
			XYZ origin2 = hypiping.EndConnector.Origin;
			FamilyInstance familyInstance = this.doc.Create.NewFamilyInstance(xyzPoint, familySymbol, this.doc.ActiveView.GenLevel, (Autodesk.Revit.DB.Structure.StructuralType)0);
			Element elementById = this.doc.GetElementById(familyInstance.Id);
			this.doc.Regenerate();
			if (this.sprinlkerLocationType == 1)
			{
				new ConnectHelper().AlignElement(origin, origin2, elementById);
			}
			if (this.sprinklerCategory == 3 || this.sprinklerCategory == 4)
			{
				Connector elementConnector = YJKRevitTools.GetElementConnector(elementById);
				double num;
				if (this.sprinlkerLocationType == 1)
				{
					num = YJKRevitTools.GetTwoXYVectorAngle(elementConnector.CoordinateSystem.BasisZ, origin.Subtract(origin2)) * 180.0 / Math.PI;
					if (num > 180.0)
					{
						num -= 180.0;
					}
				}
				else
				{
					num = YJKRevitTools.GetTwoXYVectorAngle(elementConnector.CoordinateSystem.BasisZ, hypiping.GetXYVectorPointToPiping(xyzPoint)) * 180.0 / Math.PI;
				}
				new YJKRotateFamilyInstance().RotateElem(this.doc, familyInstance, num);
				this.doc.Regenerate();
			}
			return elementById;
		}

		private Pipe SetSprinklerParam(Element elemSprinkler)
		{
			Pipe result = null;
			new AuxiliaryLineOperate();
			HYParametersSetting hyparametersSetting = new HYParametersSetting(this.uiApp);
			Parameter parameter = (elemSprinkler as FamilyInstance).Symbol.GetParameter(BuiltInParameter.RBS_FP_SPRINKLER_K_FACTOR_PARAM);
			if (parameter != null)
			{
				parameter.Set(this.sprinklersPara.Kratio);
			}
			Parameter parameter2 = elemSprinkler.GetParameter("喷淋半径");
			if (parameter2 == null)
			{
				hyparametersSetting.SetSprinklersRudioShareParam();
				parameter2 = elemSprinkler.GetParameter("喷淋半径");
			}
			if (parameter2 != null)
			{
				parameter2.Set(UnitConvert.CovertToAPI(this.sprinklersPara.Radius * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
			}
			Parameter parameter3 = elemSprinkler.GetParameter("危险等级");
			if (parameter3 == null)
			{
				hyparametersSetting.SetSprinklersDangerShareParam();
				parameter3 = elemSprinkler.GetParameter("危险等级");
			}
			if (parameter3 != null)
			{
				parameter3.Set(this.sprinklersPara.Danger);
			}
			Parameter parameter4 = elemSprinkler.GetParameter(BuiltInParameter.FAMILY_LEVEL_PARAM);
			if (parameter4 != null)
			{
				parameter4.Set(this.doc.ActiveView.GenLevel.Id);
			}
			Parameter parameter5 = elemSprinkler.GetParameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
			if (this.sprinklerCategory != 5)
			{
				if (parameter5 != null)
				{
					parameter5.Set(UnitConvert.CovertToAPI(this.sprinklersPara.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
				}
			}
			else
			{
				result = LaySprinklerHelper.LayUpDownSprinkler(this.doc, elemSprinkler, 0, this.sprinklersPara);
			}
			CreateProtectRange createProtectRange = new CreateProtectRange();
			if (this.sprinklersPara.Range && (int)this.doc.ActiveView.ViewType != 4)
			{
				List<Element> collection = new List<Element>
				{
					elemSprinkler
				};
				createProtectRange.CreatActiveViewDetailCurve(this.doc, collection, HyRangeCheckMajor.HyGPS);
			}
			this.doc.Regenerate();
			return result;
		}

		public static Pipe LayUpDownSprinkler(Autodesk.Revit.DB.Document doc, Element elem, int layType, SprinklersParam sprinklersPara)
		{
			Parameter parameter = elem.GetParameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
			Connector elementConnector = YJKRevitTools.GetElementConnector(elem);
			double num = elementConnector.Radius * 2.0;
			XYZ basisZ = elementConnector.CoordinateSystem.BasisZ;
			YJKRotateFamilyInstance hyrotateFamilyInstance = new YJKRotateFamilyInstance();
			double num2 = sprinklersPara.OffSet * 1000.0;
			Element elementById;
			if (basisZ.Z > 0.0)
			{
				ICollection<ElementId> source = ElementTransformUtils.CopyElement(doc, elem.Id, new XYZ(0.0, 0.0, (num2 + 300.0) / 304.8));
				if (parameter != null)
				{
					parameter.Set(UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0 - 300.0, (Autodesk.Revit.DB.DisplayUnitType)2));
				}
				elementById = doc.GetElementById(source.ElementAt(0));
			}
			else
			{
				ICollection<ElementId> source = ElementTransformUtils.CopyElement(doc, elem.Id, new XYZ(0.0, 0.0, (num2 - 300.0) / 304.8));
				if (parameter != null)
				{
					parameter.Set(UnitConvert.CovertToAPI(sprinklersPara.OffSet * 1000.0 + 300.0, (Autodesk.Revit.DB.DisplayUnitType)2));
				}
				elementById = doc.GetElementById(source.ElementAt(0));
			}
			Connector elementConnector2 = YJKRevitTools.GetElementConnector(elementById);
			LocationPoint locationPoint = elementById.Location as LocationPoint;
			hyrotateFamilyInstance.RotateElem(elementById as FamilyInstance, locationPoint.Point, new XYZ(1.0, 0.0, 0.0), 180.0);
			PipingSystemType pipingSystemType = null;
			foreach (Element element in YJKElementFilter.GetElementByClass(typeof(PipingSystemType), doc))
			{
				pipingSystemType = (element as PipingSystemType);
				if ((int)pipingSystemType.SystemClassification == 23)
				{
					break;
				}
			}
			PipeType pipeType = YJKElementFilter.GetElementByClass(typeof(PipeType), doc)[sprinklersPara.PipeType] as PipeType;
			Pipe pipe = Pipe.Create(doc, pipingSystemType.Id, pipeType.Id, doc.ActiveView.GenLevel.Id, elementConnector.Origin, elementConnector2.Origin);
			new YJKPiping<Pipe>(pipe).SetDiameter(num * 304.8);
			doc.Regenerate();
			YJKRevitTools.ConnectTwoElement(elementConnector, pipe);
			YJKRevitTools.ConnectTwoElement(elementConnector2, pipe);
			doc.Regenerate();
			return pipe;
		}

		private bool ConnPointSprinkler(Element elemSprinkler, Pipe pipe)
		{
			bool result;
			try
			{
				string a = "";
				FamilySymbol familySymbolByName = YJKRevitTools.GetFamilySymbolByName("Fitting", "水管三通", this.doc, ref a);
				Connector elementConnector = YJKRevitTools.GetElementConnector(elemSprinkler);
				double num = elementConnector.Radius * 2.0;
				XYZ basisZ = elementConnector.CoordinateSystem.BasisZ;
				Pipe pipe2 = YJKRevitTools.NewPipe(pipe, elementConnector.Origin, elementConnector.Origin + basisZ * 0.2);
				new YJKPiping<Pipe>(pipe2).SetDiameter(num * 304.8);
				this.doc.Regenerate();
				YJKRevitTools.ConnectTwoElement(elementConnector, pipe2);
				new YJKPipeConnectorHelper().TPipeConnectRPipe(pipe2, pipe, this.doc, familySymbolByName, false, 4, ref a, false);
				if (a != "")
				{
					new HYPipeConnect().NewSomeConnect(new List<Pipe>
					{
						pipe,
						pipe2
					});
				}
				this.doc.Regenerate();
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private bool ConnUpDownSprinkler(Pipe pipe, Pipe upDownPipe, XYZ xyzLayPoint)
		{
			YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(pipe);
			HYPipeConnect hypipeConnect = new HYPipeConnect();
			bool result;
			try
			{
				LocationCurve locationCurve = upDownPipe.Location as LocationCurve;
				XYZ xyz = (locationCurve.Curve.GetEndPoint(0) + locationCurve.Curve.GetEndPoint(1)) / 2.0;
				xyzLayPoint = hypiping.GetLineProject(xyzLayPoint);
				if (this.sprinlkerLocationType == 1)
				{
					ElementTransformUtils.MoveElement(this.doc, upDownPipe.Id, new XYZ(0.0, 0.0, xyzLayPoint.Z - xyz.Z));
					this.doc.Regenerate();
					hypipeConnect.NewSomeConnect(new List<Pipe>
					{
						upDownPipe,
						pipe
					});
				}
				else
				{
					Pipe pipe2 = YJKRevitTools.NewPipe(upDownPipe, xyz, new XYZ(xyzLayPoint.X, xyzLayPoint.Y, xyz.Z));
					YJKPipeConnectorHelper hypipeConnectorHelper = new YJKPipeConnectorHelper();
					FamilySymbol familySymbolByName = YJKRevitTools.GetFamilySymbolByName("Fitting", "水管三通", this.doc, ref this.message);
					hypipeConnectorHelper.TPipeConnectRPipe(upDownPipe, pipe2, this.doc, familySymbolByName, false, 4, ref this.message, false);
					hypipeConnectorHelper.TPipeConnectRPipe(pipe2, pipe, this.doc, familySymbolByName, false, 4, ref this.message, false);
				}
				this.doc.Regenerate();
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		public bool isXYZAmolstEqual(XYZ a, XYZ b)
		{
			return Math.Abs(a.X - b.X) < 0.001 && Math.Abs(a.Y - b.Y) < 0.001 && Math.Abs(a.Z - b.Z) < 0.001;
		}

		public static XYZ TransformPoint(XYZ point, Transform transform)
		{
			double x = point.X;
			double y = point.Y;
			double z = point.Z;
			XYZ xyz = transform.get_Basis(0);
			XYZ xyz2 = transform.get_Basis(1);
			XYZ xyz3 = transform.get_Basis(2);
			XYZ origin = transform.Origin;
			double num = x * xyz.X + y * xyz2.X + z * xyz3.X + origin.X;
			double num2 = x * xyz.Y + y * xyz2.Y + z * xyz3.Y + origin.Y;
			double num3 = x * xyz.Z + y * xyz2.Z + z * xyz3.Z + origin.Z;
			return new XYZ(num, num2, num3);
		}

		public List<XYZ> GetAvoidedXYZ(List<XYZ> xyzList)
		{
			List<XYZ> list = new List<XYZ>();
			try
			{
				int num = 0;
				using (List<XYZ>.Enumerator enumerator = xyzList.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						if (Math.Abs(enumerator.Current.Y - xyzList[0].Y) < 0.001)
						{
							num++;
						}
					}
				}
				int num2 = 0;
				for (int i = 0; i < xyzList.Count; i++)
				{
					XYZ xyz = xyzList[i];
					XYZ xyz2 = this.AvoidColumn(xyz);
					if (!this.isXYZAmolstEqual(xyz2, xyz))
					{
						for (int j = num2 % num; j < xyzList.Count; j += num)
						{
							xyzList[j] = new XYZ(xyz2.X, xyzList[j].Y, xyzList[j].Z);
						}
					}
					xyz = xyz2;
					xyz2 = this.AvoidBeam(xyz);
					if (!this.isXYZAmolstEqual(xyz2, xyz))
					{
						for (int k = num2 % num; k < xyzList.Count; k += num)
						{
							xyzList[k] = new XYZ(xyz2.X, xyzList[k].Y, xyzList[k].Z);
						}
					}
					xyz = xyz2;
					list.Add(xyz);
					num2++;
				}
			}
			catch (Exception ex)
			{
				YJKMessageBox.Show(ex.Message);
			}
			return list;
		}

		private List<RevitLinkInstance> GetLinkInstance(Autodesk.Revit.DB.Document doc)
		{
			List<RevitLinkInstance> list = new List<RevitLinkInstance>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(RevitLinkInstance));
			foreach (Element element in filteredElementCollector)
			{
				RevitLinkInstance item = element as RevitLinkInstance;
				list.Add(item);
			}
			return list;
		}

		private XYZ AvoidColumn(XYZ xyz)
		{
			XYZ xyz2 = xyz;
			ElementFilter elementFilter = new ElementCategoryFilter(BuiltInCategory.OST_StructuralColumns);
			ElementCategoryFilter elementCategoryFilter = new ElementCategoryFilter(BuiltInCategory.OST_Columns);
			LogicalOrFilter logicalOrFilter = new LogicalOrFilter(elementFilter, elementCategoryFilter);
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.doc);
			filteredElementCollector.WherePasses(logicalOrFilter).OfClass(typeof(FamilyInstance));
			double num = 0.0;
			foreach (Element element in filteredElementCollector)
			{
				BoundingBoxXYZ boundingBoxXYZ = element.get_BoundingBox(this.doc.ActiveView);
				if (boundingBoxXYZ != null && xyz.X < boundingBoxXYZ.Max.X + 0.32808398950131235 && xyz.X > boundingBoxXYZ.Min.X - 0.32808398950131235 && xyz.Y < boundingBoxXYZ.Max.Y + 0.32808398950131235 && xyz.Y > boundingBoxXYZ.Min.Y - 0.32808398950131235)
				{
					xyz2 = new XYZ(boundingBoxXYZ.Min.X - 0.32808398950131235, xyz2.Y + num * (xyz.X - boundingBoxXYZ.Min.X + 0.32808398950131235), xyz2.Z);
					xyz2 = this.AvoidColumn(xyz2);
				}
			}
			List<RevitLinkInstance> linkInstance = this.GetLinkInstance(this.doc);
			if (linkInstance.Count > 0)
			{
				foreach (RevitLinkInstance revitLinkInstance in linkInstance)
				{
					Transform totalTransform = revitLinkInstance.GetTotalTransform();
					FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(revitLinkInstance.GetLinkDocument());
					filteredElementCollector2.WherePasses(logicalOrFilter);
					foreach (Element element2 in filteredElementCollector2)
					{
						BoundingBoxXYZ boundingBoxXYZ2 = element2.get_BoundingBox(revitLinkInstance.GetLinkDocument().ActiveView);
						if (boundingBoxXYZ2 != null)
						{
							XYZ xyz3 = boundingBoxXYZ2.Max + totalTransform.Origin;
							XYZ xyz4 = boundingBoxXYZ2.Min + totalTransform.Origin;
							if (xyz.X < xyz3.X + 0.32808398950131235 && xyz.X > xyz4.X - 0.32808398950131235 && xyz.Y < xyz3.Y + 0.32808398950131235 && xyz.Y > xyz4.Y - 0.32808398950131235)
							{
								xyz2 = new XYZ(xyz4.X - 0.32808398950131235, xyz2.Y + num * (xyz.X - xyz4.X + 0.32808398950131235), xyz2.Z);
								xyz2 = this.AvoidColumn(xyz2);
							}
						}
					}
				}
			}
			return xyz2;
		}

		private XYZ AvoidBeam(XYZ xyz)
		{
			XYZ xyz2 = xyz;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.doc);
			filteredElementCollector.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_StructuralFraming);
			double num = 0.0;
			foreach (Element element in filteredElementCollector)
			{
				BoundingBoxXYZ boundingBoxXYZ = element.get_BoundingBox(this.doc.ActiveView);
				if (boundingBoxXYZ != null && xyz.X < boundingBoxXYZ.Max.X + 0.32808398950131235 && xyz.X > boundingBoxXYZ.Min.X - 0.32808398950131235 && xyz.Y < boundingBoxXYZ.Max.Y + 0.32808398950131235 && xyz.Y > boundingBoxXYZ.Min.Y - 0.32808398950131235)
				{
					xyz2 = new XYZ(boundingBoxXYZ.Min.X - 0.32808398950131235, xyz2.Y + num * (xyz.X - boundingBoxXYZ.Min.X + 0.32808398950131235), xyz2.Z);
					xyz2 = this.AvoidColumn(xyz2);
				}
			}
			List<RevitLinkInstance> linkInstance = this.GetLinkInstance(this.doc);
			if (linkInstance.Count > 0)
			{
				foreach (RevitLinkInstance revitLinkInstance in linkInstance)
				{
					Transform totalTransform = revitLinkInstance.GetTotalTransform();
					filteredElementCollector.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_StructuralFraming);
					foreach (Element element2 in filteredElementCollector)
					{
						BoundingBoxXYZ boundingBoxXYZ2 = element2.get_BoundingBox(revitLinkInstance.GetLinkDocument().ActiveView);
						if (boundingBoxXYZ2 != null)
						{
							XYZ xyz3 = boundingBoxXYZ2.Max + totalTransform.Origin;
							XYZ xyz4 = boundingBoxXYZ2.Min + totalTransform.Origin;
							if (xyz.X < xyz3.X + 0.32808398950131235 && xyz.X > xyz4.X - 0.32808398950131235 && xyz.Y < xyz3.Y + 0.32808398950131235 && xyz.Y > xyz4.Y - 0.32808398950131235)
							{
								xyz2 = new XYZ(xyz4.X - 0.32808398950131235, xyz2.Y + num * (xyz.X - xyz4.X + 0.32808398950131235), xyz2.Z);
								xyz2 = this.AvoidColumn(xyz2);
							}
						}
					}
				}
			}
			return xyz2;
		}

		public List<XYZ> GetLinkDocPakings(double z)
		{
			List<XYZ> list = new List<XYZ>();
			List<RevitLinkInstance> linkInstance = this.GetLinkInstance(this.doc);
			if (linkInstance.Count > 0)
			{
				foreach (RevitLinkInstance revitLinkInstance in linkInstance)
				{
					Transform totalTransform = revitLinkInstance.GetTotalTransform();
					FilteredElementCollector filteredElementCollector = new FilteredElementCollector(revitLinkInstance.GetLinkDocument());
					filteredElementCollector.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_Parking);
					foreach (Element parking in filteredElementCollector)
					{
						XYZ centerOfParking = this.GetCenterOfParking(parking);
						if (centerOfParking != null)
						{
							list.Add(new XYZ(centerOfParking.X, centerOfParking.Y, z) + totalTransform.Origin);
						}
					}
				}
			}
			return list;
		}

		private List<XYZ> AdjustRecPoints(List<XYZ> recPoints, double offset)
		{
			return new List<XYZ>();
		}

		public List<XYZ> GetThreePointXYZ(List<XYZ> xyzList, double rowDistance, double rowSideDistance, XYZ startMin, XYZ startMax, XYZ startEnd)
		{
			List<XYZ> list = new List<XYZ>();
			List<XYZ> list2 = new List<XYZ>();
			List<XYZ> list3 = new List<XYZ>();
			XYZ xyz = startMin + (startEnd - startMax);
			Line line = Line.CreateBound(startMin, startMax);
			Curve curve = Line.CreateBound(startMin, startEnd);
			Line.CreateBound(startMax, xyz);
			Line.CreateBound(startEnd, xyz);
			double num = rowSideDistance / 304.8 / 3.0;
			double length = line.Length;
			double length2 = curve.Length;
			List<XYZ> list4 = new List<XYZ>();
			list4.Add(startMin);
			list4.Add(startMax);
			list4.Add(startEnd);
			list4.Add(xyz);
			foreach (XYZ xyz2 in xyzList)
			{
				if (LaySprinklerHelper.InsidePolygon(list4, xyz2))
				{
					list2.Add(xyz2);
				}
			}
			double num2 = this.getLargestK(list2);
			if (list2.Count > 0)
			{
				foreach (XYZ xyz3 in list2)
				{
					foreach (XYZ xyz4 in list2)
					{
						if (xyz3 != xyz4)
						{
							double num3;
							if (xyz3.X - xyz4.X == 0.0)
							{
								num3 = 100000.0;
							}
							else
							{
								num3 = (xyz3.Y - xyz4.Y) / (xyz3.X - xyz4.X);
							}
							if (Math.Abs(num3 - num2) < 0.01)
							{
								bool flag = false;
								using (List<XYZ>.Enumerator enumerator3 = list3.GetEnumerator())
								{
									while (enumerator3.MoveNext())
									{
										if (enumerator3.Current == xyz4)
										{
											flag = true;
										}
									}
								}
								if (!flag)
								{
									list3.Add(xyz4);
								}
							}
						}
					}
				}
			}
			if (num2 != 0.0)
			{
				if (num2 == 100000.0)
				{
					num2 = 0.0;
				}
				else
				{
					num2 = -1.0 / num2;
				}
			}
			else
			{
				num2 = 100000.0;
			}
			if (list3.Count > 0)
			{
				foreach (XYZ item in list3)
				{
					list.Add(item);
				}
				double num4 = rowDistance / 304.8;
				foreach (XYZ xyz5 in list3)
				{
					int num5 = 1;
					for (;;)
					{
						XYZ xyz6 = new XYZ(xyz5.X + (double)num5 * num4 / Math.Sqrt(1.0 + num2 * num2), xyz5.Y + (double)num5 * num4 * num2 / Math.Sqrt(1.0 + num2 * num2), xyz5.Z);
						if (!LaySprinklerHelper.InsidePolygon(list4, xyz6))
						{
							break;
						}
						list.Add(xyz6);
						num5++;
					}
					num5 = 1;
					for (;;)
					{
						XYZ xyz7 = new XYZ(xyz5.X - (double)num5 * num4 / Math.Sqrt(1.0 + num2 * num2), xyz5.Y - (double)num5 * num4 * num2 / Math.Sqrt(1.0 + num2 * num2), xyz5.Z);
						if (!LaySprinklerHelper.InsidePolygon(list4, xyz7))
						{
							break;
						}
						list.Add(xyz7);
						num5++;
					}
				}
			}
			return list;
		}

		public static bool InsidePolygon(List<XYZ> polygon, XYZ p)
		{
			if (polygon.Count <= 0)
			{
				return false;
			}
			int num = 0;
			XYZ xyz = polygon[0];
			int count = polygon.Count;
			for (int i = 1; i <= count; i++)
			{
				XYZ xyz2 = polygon[i % count];
				if (xyz.Y != xyz2.Y && p.Y > Math.Min(xyz.Y, xyz2.Y) && p.Y <= Math.Max(xyz.Y, xyz2.Y) && p.X <= Math.Max(xyz.X, xyz2.X))
				{
					if (xyz.X == xyz2.X)
					{
						num++;
					}
					else
					{
						double num2 = (p.Y - xyz.Y) * (xyz2.X - xyz.X) / (xyz2.Y - xyz.Y) + xyz.X;
						if (p.X <= num2)
						{
							num++;
						}
					}
				}
				xyz = xyz2;
			}
			return num % 2 != 0;
		}

		private double getLargestK(List<XYZ> xyzList)
		{
			Dictionary<double, double> dictionary = new Dictionary<double, double>();
			foreach (XYZ xyz in xyzList)
			{
				foreach (XYZ xyz2 in xyzList)
				{
					if (xyz != xyz2)
					{
						double num = 0.0;
						if (xyz.X - xyz2.X == 0.0)
						{
							num = 100000.0;
						}
						else
						{
							num = (xyz.Y - xyz2.Y) / (xyz.X - xyz2.X);
						}
						try
						{
							Dictionary<double, double> dictionary2 = dictionary;
							double key = num;
							double num2 = dictionary2[key];
							dictionary2[key] = num2 + 1.0;
						}
						catch (Exception)
						{
							dictionary.Add(num, 1.0);
						}
					}
				}
			}
			double num3 = 0.0;
			double result = 0.0;
			foreach (KeyValuePair<double, double> keyValuePair in dictionary)
			{
				if (keyValuePair.Value > num3)
				{
					num3 = keyValuePair.Value;
					result = keyValuePair.Key;
				}
			}
			return result;
		}

		public List<XYZ> GetRulesPakings(List<XYZ> innerParkingList)
		{
			List<XYZ> list = new List<XYZ>();
			double largestK = this.getLargestK(innerParkingList);
			if (innerParkingList.Count > 0)
			{
				foreach (XYZ xyz in innerParkingList)
				{
					foreach (XYZ xyz2 in innerParkingList)
					{
						if (xyz != xyz2)
						{
							double num;
							if (xyz.X - xyz2.X == 0.0)
							{
								num = 100000.0;
							}
							else
							{
								num = (xyz.Y - xyz2.Y) / (xyz.X - xyz2.X);
							}
							if (Math.Abs(num - largestK) < 0.01)
							{
								bool flag = false;
								using (List<XYZ>.Enumerator enumerator3 = list.GetEnumerator())
								{
									while (enumerator3.MoveNext())
									{
										if (enumerator3.Current == xyz2)
										{
											flag = true;
										}
									}
								}
								if (!flag)
								{
									list.Add(xyz2);
								}
							}
						}
					}
				}
			}
			return list;
		}

		public List<XYZ> GetParkingXYZ(List<XYZ> xyzList, LayAreaParameter layAreaParameter, XYZ point1, XYZ point2, XYZ point3)
		{
			List<XYZ> list = new List<XYZ>();
			List<XYZ> list2 = new List<XYZ>();
			XYZ xyz = point1 + (point3 - point2);
			List<XYZ> list3 = new List<XYZ>();
			list3.Add(point1);
			list3.Add(point2);
			list3.Add(point3);
			list3.Add(xyz);
			foreach (XYZ xyz2 in xyzList)
			{
				if (LaySprinklerHelper.InsidePolygon(list3, xyz2))
				{
					list2.Add(xyz2);
				}
			}
			if (list2.Count < 1)
			{
				return list;
			}
			double z = list2[0].Z;
			List<Line> list4 = new List<Line>();
			point1 = new XYZ(point1.X, point1.Y, z);
			point2 = new XYZ(point2.X, point2.Y, z);
			point3 = new XYZ(point3.X, point3.Y, z);
			xyz = new XYZ(xyz.X, xyz.Y, z);
			Line line = Line.CreateBound(new XYZ(point1.X, point1.Y, z), new XYZ(point2.X, point2.Y, z));
			Line line2 = Line.CreateBound(new XYZ(point2.X, point2.Y, z), new XYZ(point3.X, point3.Y, z));
			Line item = Line.CreateBound(new XYZ(point3.X, point3.Y, z), new XYZ(xyz.X, xyz.Y, z));
			Line line3 = Line.CreateBound(new XYZ(xyz.X, xyz.Y, z), new XYZ(point1.X, point1.Y, z));
			list4.Add(line);
			list4.Add(line2);
			list4.Add(item);
			list4.Add(line3);
			List<XYZ> list5 = this.GetRulesPakings(list2);
			List<XYZ> endPoints = this.getEndPoints(list5);
			if (endPoints != null)
			{
				XYZ xyz3 = endPoints[0] - endPoints[1];
				XYZ xyz4;
				if (xyz3.Y == 0.0)
				{
					xyz4 = new XYZ(0.0, 1.0, 0.0);
				}
				else
				{
					xyz4 = new XYZ(1.0, -xyz3.X / xyz3.Y, 0.0);
				}
				list5 = this.ExtendPakings(list5, endPoints, line2, line3, layAreaParameter, list3);
				foreach (XYZ xyz5 in list5)
				{
					YJKLine line4 = new YJKLine(Line.CreateBound(xyz5, xyz5 + Math.Sqrt(line2.Length * line2.Length + line.Length * line.Length) * xyz4));
					YJKLine line5 = new YJKLine(Line.CreateBound(xyz5, xyz5 - Math.Sqrt(line2.Length * line2.Length + line.Length * line.Length) * xyz4));
					XYZ insectPointInRec = this.GetInsectPointInRec(line4, list4);
					XYZ insectPointInRec2 = this.GetInsectPointInRec(line5, list4);
					list.Add(xyz5);
					if (insectPointInRec != null)
					{
						List<XYZ> pointOfDividedLine = this.GetPointOfDividedLine((int)layAreaParameter.RowDistance, (int)layAreaParameter.LessDistance, (int)layAreaParameter.ColDistanceSide, 0, 100, xyz5, insectPointInRec);
						list.AddRange(pointOfDividedLine);
					}
					if (insectPointInRec2 != null)
					{
						List<XYZ> pointOfDividedLine2 = this.GetPointOfDividedLine((int)layAreaParameter.RowDistance, (int)layAreaParameter.LessDistance, (int)layAreaParameter.ColDistanceSide, 0, 100, xyz5, insectPointInRec2);
						list.AddRange(pointOfDividedLine2);
					}
				}
			}
			return list;
		}

		private XYZ GetInsectPointInRec(YJKLine line, List<Line> recLines)
		{
			foreach (Line otherLine in recLines)
			{
				XYZ xyz = line.IntersectionPoint(otherLine);
				if (xyz != null)
				{
					return xyz;
				}
			}
			return null;
		}

		private List<XYZ> ExtendPakings(List<XYZ> ruledParkingList, List<XYZ> endPoints, Line line2, Line line4, LayAreaParameter layAreaParameter, List<XYZ> recPointList)
		{
			List<XYZ> list = new List<XYZ>();
			YJKLine hyline = new YJKLine(Line.CreateBound(endPoints[1], endPoints[0]));
			XYZ xyz = hyline.IntersectionPoint(line2, true);
			XYZ xyz2 = hyline.IntersectionPoint(line4, true);
			YJKMessageBox.Show(xyz.ToString() + "," + xyz2.ToString());
			if (xyz.DistanceTo(endPoints[0]) < xyz.DistanceTo(endPoints[1]))
			{
				list.Add(xyz);
				list.Add(xyz2);
			}
			else
			{
				list.Add(xyz2);
				list.Add(xyz);
			}
			List<XYZ> pointOfDividedLine = this.GetPointOfDividedLine((int)layAreaParameter.RowDistance, (int)layAreaParameter.LessDistance, (int)layAreaParameter.ColDistanceSide, 0, 100, endPoints[0], list[0]);
			List<XYZ> pointOfDividedLine2 = this.GetPointOfDividedLine((int)layAreaParameter.RowDistance, (int)layAreaParameter.LessDistance, (int)layAreaParameter.ColDistanceSide, 0, 100, endPoints[1], list[1]);
			YJKMessageBox.Show(pointOfDividedLine.Count.ToString() + pointOfDividedLine2.Count.ToString());
			foreach (XYZ xyz3 in pointOfDividedLine)
			{
				if (LaySprinklerHelper.InsidePolygon(recPointList, xyz3))
				{
					ruledParkingList.Add(xyz3);
				}
			}
			foreach (XYZ xyz4 in pointOfDividedLine2)
			{
				if (LaySprinklerHelper.InsidePolygon(recPointList, xyz4))
				{
					ruledParkingList.Add(xyz4);
				}
			}
			return ruledParkingList;
		}

		public List<XYZ> getEndPoints(List<XYZ> xyzList)
		{
			List<XYZ> list = new List<XYZ>();
			if (xyzList.Count == 0)
			{
				return null;
			}
			if (xyzList.Count == 1)
			{
				list.Add(xyzList[0]);
			}
			else
			{
				double num = double.MinValue;
				Line line = null;
				foreach (XYZ xyz in xyzList)
				{
					foreach (XYZ xyz2 in xyzList)
					{
						if (xyz != xyz2)
						{
							try
							{
								Line line2 = Line.CreateBound(xyz, xyz2);
								if (line2.Length > num)
								{
									line = line2;
									num = line2.Length;
								}
							}
							catch
							{
							}
						}
					}
				}
				if (line != null)
				{
					list.Add(line.Tessellate()[0]);
					list.Add(line.Tessellate()[1]);
				}
			}
			return list;
		}

		public List<XYZ> GetPointOfDividedLine(int maxDis, int minDis, int maxSide, int minSide, int disDivisor, XYZ sLinePnt, XYZ eLinePnt)
		{
			List<XYZ> list = new List<XYZ>();
			double num = new YJKLine(sLinePnt, eLinePnt).Line.Length * 304.8;
			int i = Convert.ToInt32((num - num % (double)maxDis) / (double)maxDis);
			int num2 = maxDis - maxDis % disDivisor;
			int num3 = minDis + (disDivisor - minDis % disDivisor);
			int num4 = 0;
			int num5 = 0;
			if (i == 0)
			{
				list.Add(sLinePnt.Add(eLinePnt) / 2.0);
				return list;
			}
			while (i > 0)
			{
				for (int j = num2; j >= num3; j -= disDivisor)
				{
					if (num - (double)(i * j) >= (double)(2 * maxSide))
					{
						i = 0;
						break;
					}
					num4 = i;
					num5 = j;
				}
				if (i == 1)
				{
					break;
				}
				i--;
			}
			XYZ xyz = eLinePnt.Subtract(sLinePnt).Normalize();
			double num6 = (num - (double)(num4 * num5)) / 2.0;
			num6 += (double)disDivisor - num6 % (double)disDivisor;
			for (int k = 0; k <= num4; k++)
			{
				XYZ item = sLinePnt + num6 / 304.8 * xyz + (double)(k * num5) / 304.8 * xyz;
				list.Add(item);
			}
			return list;
		}

		public List<XYZ> GetParkingXYZ(List<XYZ> xyzList, double colDistance, double rowDistance, XYZ startMin, XYZ startMax)
		{
			List<XYZ> list = new List<XYZ>();
			List<XYZ> list2 = new List<XYZ>();
			if (xyzList.Count > 1)
			{
				double num = startMin.X;
				double num2 = startMax.X;
				if (num > num2)
				{
					double num3 = num;
					num = num2;
					num2 = num3;
				}
				double num4 = startMin.Y;
				double num5 = startMax.Y;
				if (num4 > num5)
				{
					double num6 = num4;
					num4 = num5;
					num5 = num6;
				}
				foreach (XYZ xyz in xyzList)
				{
					if (num < xyz.X && xyz.X < num2 && xyz.Y > num4 && xyz.Y < num5)
					{
						list2.Add(xyz);
					}
				}
				if (list2.Count > 0)
				{
					IEnumerable<double> enumerable = (from n in list2
					group n.Y by n.Y into g
					orderby g.Count<double>() descending
					select g).First<IGrouping<double, double>>();
					int num7 = 0;
					double num8 = 0.0;
					foreach (double num9 in enumerable)
					{
						num7++;
						num8 = num9;
					}
					IEnumerable<double> enumerable2 = (from n in list2
					group n.X by n.X into g
					orderby g.Count<double>() descending
					select g).First<IGrouping<double, double>>();
					int num10 = 0;
					double num11 = 0.0;
					foreach (double num12 in enumerable2)
					{
						num10++;
						num11 = num12;
					}
					if (num10 > num7)
					{
						int num13 = (int)((num2 - num11) / (colDistance / 304.8));
						int num14 = (int)((num11 - num) / (colDistance / 304.8));
						if (num13 > 0)
						{
							num2 = num11 + (double)num13 * (colDistance / 304.8);
						}
						else
						{
							num2 = num11;
						}
						if (num14 > 0)
						{
							num = num11 - (double)num14 * (colDistance / 304.8);
						}
						else
						{
							num = num11;
						}
						int num15 = 0;
						while (num + (double)num15 * (colDistance / 304.8) <= num2)
						{
							double num16 = num + (double)num15 * (colDistance / 304.8);
							foreach (XYZ xyz2 in list2)
							{
								if (Math.Abs(xyz2.X - num11) < 0.001)
								{
									list.Add(new XYZ(num16, xyz2.Y, xyz2.Z));
								}
							}
							num15++;
						}
					}
					else
					{
						int num17 = (int)((num5 - num8) / (rowDistance / 304.8));
						int num18 = (int)((num8 - num4) / (rowDistance / 304.8));
						if (num17 > 0)
						{
							num5 = num8 + (double)num17 * (rowDistance / 304.8);
						}
						else
						{
							num5 = num8;
						}
						if (num18 > 0)
						{
							num4 = num8 - (double)num18 * (rowDistance / 304.8);
						}
						else
						{
							num4 = num8;
						}
						int num19 = 0;
						while (num4 + (double)num19 * (rowDistance / 304.8) <= num5)
						{
							double num20 = num4 + (double)num19 * (rowDistance / 304.8);
							foreach (XYZ xyz3 in list2)
							{
								if (Math.Abs(xyz3.Y - num8) < 0.001)
								{
									list.Add(new XYZ(xyz3.X, num20, xyz3.Z));
								}
							}
							num19++;
						}
					}
				}
			}
			return list;
		}

		public XYZ GetCenterOfParking(Element parking)
		{
			XYZ result;
			try
			{
				double num = 0.0;
				double num2 = 0.0;
				double x = (parking as FamilyInstance).FacingOrientation.X;
				double y = (parking as FamilyInstance).FacingOrientation.Y;
				if (x != 0.0)
				{
					double num3 = y / x;
				}
				foreach (object obj in (parking as FamilyInstance).Symbol.Parameters)
				{
					Parameter parameter = (Parameter)obj;
					if (parameter.Definition.Name == "停车场长度")
					{
						num = Convert.ToDouble(parameter.AsValueString()) / 304.8;
					}
					if (parameter.Definition.Name == "停车场宽度")
					{
						num2 = Convert.ToDouble(parameter.AsValueString()) / 304.8;
					}
				}
				BoundingBoxXYZ boundingBoxXYZ = parking.get_BoundingBox(this.doc.ActiveView);
				double num4 = (boundingBoxXYZ.Max.X + boundingBoxXYZ.Min.X) / 2.0;
				double num5 = (boundingBoxXYZ.Max.Y + boundingBoxXYZ.Min.Y) / 2.0;
				XYZ point = (parking.Location as LocationPoint).Point;
				if (Math.Abs(num4 - point.X) > Math.Abs(num5 - point.Y))
				{
					double num6 = num;
					num = num2;
					num2 = num6;
				}
				double num7;
				if (num4 > point.X)
				{
					num7 = point.X + num2 / 2.0;
				}
				else
				{
					num7 = point.X - num2 / 2.0;
				}
				double num8;
				if (num5 > point.Y)
				{
					num8 = point.Y + num / 2.0;
				}
				else
				{
					num8 = point.Y - num / 2.0;
				}
				result = new XYZ(num7, num8, 0.0);
			}
			catch (Exception)
			{
				result = null;
			}
			return result;
		}

		public string GetDangelLevel()
		{
			return new ModelAnalyser(this.doc).GetDangerLevel();
		}

		private UIApplication uiApp;

		private Document doc;

		private Selection sel;

		private string message = "";

		private SprinklersParam sprinklersPara;

		private int sprinklerCategory;

		private int sprinlkerLocationType;

		private const double dUpDownPipe = 300.0;

		public class SprinlkersPipeSelectionFilter : ISelectionFilter
		{
			public bool AllowElement(Element elem)
			{
                return elem is Pipe && (int)((elem as Pipe).MEPSystem as PipingSystem).SystemType == 23 && !YJKRevitTools.isRiserPiping(elem);
			}

			public bool AllowReference(Reference reference, XYZ position)
			{
				return false;
			}
		}
	}
}
